package com.toycloud.system.utils;

import com.iflytek.cssp.CSSPClient;
import com.iflytek.cssp.exception.CSSPException;
import com.iflytek.cssp.model.ObjectMetadata;
import com.iflytek.cssp.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * Created by TonyHo on 20/12/2016.
 */
@Repository
@Slf4j
public class Openstorage {

    private static final String ACCOUNT = "hipanda";

    private static final String ACCESS_KEY_ID = "ae851fee56c241af925b36bc67267e85";
    private static final String ACCESS_SECRET = "c111b64da78146fea14121ced2316465";
    private static final String COM_URL = "http://hipanda.hfdn.openstorage.cn/";
    private static final String RETURN_URL = "http://hipanda.hf.openstorage.cn/";
    private static final String PRIVRES_KEY = "UG9egbforqN05dwQjMPpXsLb9JohYqys";

    //新的域名 toycloud
    private static final String NEW_COMMON_URL = "https://hipanda-cdn-ws.toycloud.com/";
    private static final String NEW_RETURN_URL = "https://hipanda-cdn-ws.toycloud.com/";

    /**
     * 上传文件至云存储
     */
    public String uploadFile(InputStream stream, String containerName, String floder, String fileName) {
        /*****完整路径*****/
        String toyFilePath = StringUtils.hasLength(floder) ? floder + "/" + fileName : fileName;
        boolean success = false;
//        if (VIDEO.equals(containerName)) {
//            return "";
//        }
        String url = COM_URL + containerName;
        try {
            CSSPClient client = new CSSPClient();
            client.Client(ACCESS_KEY_ID, ACCESS_SECRET, url);
            // 创建上传 Object 的 Metadata
            ObjectMetadata meta = new ObjectMetadata();
            // 必须设置 ContentLength
            meta.setContent_Length(stream.available());
            System.out.println("上传的完整路径：" + RETURN_URL + containerName + "/" + toyFilePath);
            // 上传
            PutObjectResult result;
            result = client.putObject(toyFilePath, stream, meta);
            if (result != null) {
                success = true;
                System.out.println(RETURN_URL + containerName + "/" + toyFilePath);

            }
        } catch (CSSPException | IOException | NullPointerException e) {
        } finally {
            //如果失败，100毫秒之后再次尝试
            if (success) {
                return RETURN_URL + containerName + "/" + toyFilePath;
            } else {
                return "";
            }
        }
    }

    /**
     * 上传文件至云存储（新地址）
     */
    public String uploadFileNew(InputStream stream, String containerName, String floder, String fileName) {
        /*****完整路径*****/
        String toyFilePath = StringUtils.hasLength(floder) ? floder + "/" + fileName : fileName;
        boolean success = false;
        String url = COM_URL + containerName;
        try {
            log.info("upload file " + fileName + " " + containerName);
            CSSPClient client = new CSSPClient();
            client.Client(ACCESS_KEY_ID, ACCESS_SECRET, url);
            // 创建上传 Object 的 Metadata
            ObjectMetadata meta = new ObjectMetadata();
            // 必须设置 ContentLength
            meta.setContent_Length(stream.available());
            System.out.println("上传的完整路径：" + NEW_RETURN_URL + containerName + "/" + toyFilePath);
            // 上传
            PutObjectResult result;
            result = client.putObject(toyFilePath, stream, meta);
            if (result != null) {
                success = true;
                System.out.println(NEW_RETURN_URL + containerName + "/" + toyFilePath);

            }
        } catch (CSSPException | IOException | NullPointerException e) {
            log.error("fail upload iflytek cloud storage=>" + e);
        } finally {
            if (success) {
                System.out.println(NEW_RETURN_URL + containerName + "/" + toyFilePath);
                return NEW_RETURN_URL + containerName + "/" + toyFilePath;
            } else {
                return "";
            }
        }
    }

    /**
     * 删除云存储文件
     */
    public Boolean deleteFile(String container, String oldUrl) {
        try {
            String url = COM_URL + container;
            CSSPClient client = new CSSPClient();
            client.Client(ACCESS_KEY_ID, ACCESS_SECRET, url);
            oldUrl = oldUrl.replace(RETURN_URL + container + "/", "");
            return client.deleteObject(oldUrl);
        } catch (Throwable e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取加密且具有时效的文件地址
     * 容器名称:privres
     * sub:v1
     */
    public String getPrivresUrl(String baseUrl, long expires) {
        String url = baseUrl.replace(RETURN_URL, "");
        String etime = Long.toString(System.currentTimeMillis() / 1000 + expires);

        String path = "/v1/" + ACCOUNT + "/" + url;
        String data = "GET" + "\n" + etime + "\n" + path;

        String token = this.getSha1(data);
        return baseUrl + "?token=" + token + "&e=" + etime;
    }

    private String getSha1(String data) {
        byte[] result = null;
        try {
            //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
            SecretKeySpec signinKey = new SecretKeySpec(PRIVRES_KEY.getBytes("UTF-8"), "HmacSHA1");
            //生成一个指定 Mac 算法 的 Mac 对象
            Mac mac = Mac.getInstance("HmacSHA1");
            //用给定密钥初始化 Mac 对象
            mac.init(signinKey);
            //完成 Mac 操作
            result = mac.doFinal(data.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            System.err.println(e.getMessage());
        } catch (InvalidKeyException e) {
            System.err.println(e.getMessage());
        } catch (IllegalStateException | UnsupportedEncodingException e) {
            System.err.println(e.getMessage());
        }
        if (null != result) {
            return this.toHex(result).toLowerCase();
        } else {
            return null;
        }
    }

    private String toHex(byte[] buffer) {
        StringBuffer sb = new StringBuffer(buffer.length * 2);
        for (int i = 0; i < buffer.length; i++) {
            sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16));
            sb.append(Character.forDigit(buffer[i] & 15, 16));
        }
        return sb.toString();
    }

//    public void multipartUpload(String filePath, String containerName) {
//        String objectName = "";
//        // CSSPClient初始化
//        String url = COM_URL + containerName;
//        CSSPClient client = new CSSPClient();
//        try {
//            client.Client(ACCESS_KEY_ID, ACCESS_SECRET, url);
//        } catch (CSSPException e) {
//            e.printStackTrace();
//        }
//        //分片上传初始化
//        String UploadID = "";
//        long count = 0;
//        try {
//            UploadID = initiateMultipartUploadExample(client, objectName);
//        } catch (CSSPException | IOException e) {
//            log.error("初始化错误" + e.getMessage());
//        }
//        //分割文件，
//        //partfilename 分割之后的文件命名为 partfilename_i
//        // 其中 i 表示每个分段的编号
//        try {
//            count = divide(filePath, 1024);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
////        String partfilename = "your-partFile-name";
//
//        // 创建 uploadPart，上传大文件每个分块
//        try {
//            for (int i = 0; i < count; i++) {
//                File partFile = new File(filePath + "_" + i);
//// 获取文件流
//                FileInputStream fis = new FileInputStream(partFile);
//                long size = partFile.length();
//                PutObjectResult result1 = client.uploadPart(objectName, fis, size, null, UploadID,
//                        i + 1);
//                fis.close();
//            }
//        } catch (CSSPException | IOException e) {
//            log.error("上传分片文件错误：" + e.getMessage());
//        }
//        //完成
//        try {
//            completeMultipartUploadExample(client, "", "");
//        } catch (CSSPException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    public String initiateMultipartUploadExample(CSSPClient client, String objectName) throws CSSPException, IOException {
//        // 开始 Multipart Upload
//        InitiateMultipartUploadResult initiateMultipartUploadResult =
//                client.initiateMultipartUploadRequest(objectName);
//        // 打印 UploadId
//        System.out.println("UploadId: " + initiateMultipartUploadResult.getUploadID());
//        return initiateMultipartUploadResult.getUploadID();
//    }
//
//    public void completeMultipartUploadExample(CSSPClient client, String objectname, String UploadID) throws
//            CSSPException, IOException {
//        //完成分块上传
//        PutObjectResult completeMultipartUploadReuslt =
//                client.completeMultipartUpload(objectname, UploadID);
//    }
//
//    public static long divide(String name, long size) throws Exception {
//        File file = new File(name);
//        long number;
//// 计算分割后的文件数量
//        if (0 == file.length() % size) {
//            number = file.length() / size;
//        } else {
//            number = file.length() / size + 1;
//        }
//        FileInputStream fis = new FileInputStream(file);
//        BufferedInputStream bis = new BufferedInputStream(fis);
//// 开始分割
//        byte[] buf = new byte[1];
//        for (int i = 0; i < number; ++i) {
//            FileOutputStream fos = new FileOutputStream(new File(name + "_" + i));
//            BufferedOutputStream bos = new BufferedOutputStream(fos);
//            long curSize = 0L;
//            while (bis.read(buf) != -1) {
//                bos.write(buf);
//                curSize++;
//                if (curSize == size) // 已经分割成了一个小文件
//                {
//                    bos.flush();
//                    bos.close();
//                    break;
//                }
//            }
//            if (curSize < size) // 打包剩下的数据
//            {
//                bos.flush();
//                bos.close();
//                break;
//            }
//        }
//        System.out.println("分割完成");
//        return number;
//    }
}
